﻿using AutoMapper;
using DFGK.WMS.Common.Web;
using DFGK_WMS.Context;
using DFGK_WMS.IRepository;
using DFGK_WMS.Model.DTO;
using DFGK_WMS.Model.Models;
using NPOI.XSSF.UserModel.Helpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DFGK_WMS.Repository
{
    public class PDASelectOutboundRepository : BaseRepository<TShippingOrderDetail>, IPDASelectOutboundRepository
    {
        private ITOutboundOrderDetailRepository TOutboundOrderDetail;

        public PDASelectOutboundRepository(DFGK_DB context, ITOutboundOrderDetailRepository TOutboundOrderDetail, IMapper mapper) : base(context, mapper)
        {
            this.TOutboundOrderDetail = TOutboundOrderDetail;
        }

        /// <summary>
        /// 拣选出库
        /// </summary>
        /// <param name="PalletBarcode"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public bool GetSelectShipping(string PalletBarcode,string ShippingOrderSn,/*decimal OutQty,*/ out string msg)
        {
            using (var tran = Context.Database.BeginTransaction())
                try
                {
                    msg = "";
                    //查询是否有此托盘
                    var palletBarAll = Context.TPallets.Where(x => x.PalletBarcode == PalletBarcode).ToList();
                    if (palletBarAll.Count() <= 0)
                    {
                        msg = "未查询到此托盘";
                        tran.Rollback();
                        return false;
                    }
                    //查询是否有拣选台
                    var stations = Context.TStations
                        .Where(x => x.FunctionType == 4 && x.Status == 1);
                    if (stations.Count() <= 0)
                    {
                        msg = "暂无可用拣选台";
                        tran.Rollback();
                        return false;
                    }

                    //根据托盘查询出库单
                    var palletBar = palletBarAll.First();
                    var shippingListAll = Context.TShippingLockCells
                        .Where(x => x.PalletBarcode == PalletBarcode && x.CellCode == palletBar.LocationCode)
                        .OrderByDescending(x => x.CreateDate)
                        .ToList();
                    if (shippingListAll.Count() <= 0)
                        {
                        msg = "未查询到出库单相关数据";
                        tran.Rollback();
                        return false;
                    }
                    var shippingOrderAll = Context.TShippingOrderDetails.First(x => x.OrderSn == ShippingOrderSn);
                    if (shippingOrderAll == null)
                    {
                        msg = "此托盘暂无创建出库单";
                        tran.Rollback();
                        return false;
                    }
                    if(shippingOrderAll.Status == 4)
                    {
                        msg = shippingOrderAll.OrderSn + "出库单已完成,暂时无法完成拣选";
                        tran.Rollback();
                        return false;
                    }

                    //查询库存表中此托盘有多少物料
                    var palletBarcodeInInventory = Context.TInventories.Where(x => x.PalletBarcode == PalletBarcode).ToList();
                    if (palletBarcodeInInventory.Count == 0)
                    {
                        msg = "此托盘中不存在物料";
                        tran.Rollback();
                        return false;
                    }
                    else if (palletBarcodeInInventory.Count() == 1)
                    {
                        if (palletBarcodeInInventory.First().MaterialCode != shippingListAll.First().MaterialCode)
                        {
                            msg = "此物料未创建出库单" + shippingListAll.First().MaterialCode;
                            tran.Rollback();
                            return false;
                        }
                        if (palletBarcodeInInventory.First().AvailableQty > shippingListAll.First().OutQty)
                        {
                            //回流调动堆垛机
                            TaskLiku task = new TaskLiku()
                            {
                                taskId = shippingListAll.First().OrdeSn,
                                taskSubType = "IN",
                                startPositionId = stations.First().Code,
                                endPositionId = palletBarAll.First().LocationCode,
                                palletCode = palletBarAll.First().PalletBarcode
                            };
                            HttpHelper.WCSSendPostRequest("Api/ApiWCS/ReceiveTask", task);

                            //创建回流入库单
                            TReceivingOrderDetail receivingOrderDetail = new TReceivingOrderDetail();
                            DateTime now = DateTime.Now;
                            string year = now.Year.ToString();
                            string month = now.Month.ToString().PadLeft(2, '0');
                            string day = now.Day.ToString().PadLeft(2, '0');
                            string hour = now.Hour.ToString().PadLeft(2, '0');
                            string minute = now.Minute.ToString().PadLeft(2, '0');
                            string second = now.Second.ToString().PadLeft(2, '0');
                            receivingOrderDetail.OrderSn = "R" + $"{year}{month}{day}{hour}{minute}{second}";
                            receivingOrderDetail.BillType = 6;
                            receivingOrderDetail.WarehouseCode = shippingOrderAll.WarehouseCode;
                            var warehouseList = Context.TWarehouses.Where(x => x.Code == shippingOrderAll.WarehouseCode);
                            if (warehouseList.Count() <= 0)
                            {
                                msg = "未查询到库房";
                                tran.Rollback();
                                return false;
                            }
                            receivingOrderDetail.WarehouseName = warehouseList.First().Name;
                            receivingOrderDetail.MaterialId = shippingOrderAll.MaterialId;
                            receivingOrderDetail.MaterialCode = shippingOrderAll.MaterialCode;
                            receivingOrderDetail.MaterialName = shippingOrderAll.MaterialName;
                            receivingOrderDetail.MaterialTypeCode = shippingOrderAll.MaterialTypeCode;
                            receivingOrderDetail.AreaCode = shippingOrderAll.AreaCode;
                            receivingOrderDetail.AreaName = shippingOrderAll.AreaName;
                            receivingOrderDetail.PalletBarcode = PalletBarcode;
                            receivingOrderDetail.Qty = palletBarcodeInInventory.First().AvailableQty - shippingListAll.First().OutQty;
                            receivingOrderDetail.ReceivedQty = palletBarcodeInInventory.First().AvailableQty - shippingListAll.First().OutQty;
                            receivingOrderDetail.UnitId = shippingOrderAll.UnitId;
                            receivingOrderDetail.UnitName = shippingOrderAll.UnitName;
                            receivingOrderDetail.Erpcode = shippingOrderAll.Erpcode;
                            receivingOrderDetail.BatchNo = shippingOrderAll.BatchNo;
                            receivingOrderDetail.SmallBatchNo = shippingOrderAll.SmallBatchNo;
                            receivingOrderDetail.OwnerId = shippingOrderAll.OwnerId;
                            receivingOrderDetail.OwnerName = shippingOrderAll.OwnerName;
                            receivingOrderDetail.Status = 2;
                            receivingOrderDetail.LocationId = palletBarcodeInInventory.First().LocationId;
                            receivingOrderDetail.LocationName = palletBarcodeInInventory.First().LocationName;
                            receivingOrderDetail.LocationCode = palletBarcodeInInventory.First().LocationCode;
                            receivingOrderDetail.CreateDate = DateTime.Now;
                            receivingOrderDetail.MaterialName = shippingOrderAll.MaterialName;
                            receivingOrderDetail.Status = 2;
                            Context.TReceivingOrderDetails.Add(receivingOrderDetail);

                            decimal? returnQty = palletBarcodeInInventory.First().AvailableQty - shippingListAll.First().OutQty;
                            msg = "物料:" + shippingListAll.First().MaterialName + "回流" + returnQty;
                            return false;

                        }
                        else if (palletBarcodeInInventory.First().AvailableQty == shippingListAll.First().OutQty)
                        {
                            tran.Commit();
                            return true;
                        }
                        else
                        {
                            msg = "库存数量不满足出库数量";
                            tran.Rollback();
                            return false;
                        }
                    }
                    else
                    {
                        List<TShippingOrderDetail> shippingList = new List<TShippingOrderDetail>();
                        foreach (var shipping in shippingListAll)
                        {
                            var shippingDetails = Context.TShippingOrderDetails
                                .Where(x => x.OrderSn == shipping.OrdeSn && x.Status != 4)
                                .ToList();
                            if (shippingDetails.Count() <= 0)
                            {
                                continue;
                            }
                            shippingList.AddRange(shippingDetails);
                        }
                        //遍历出库单信息并校验
                        foreach (var shipping in shippingList)
                        {
                            var InventoryList = Context.TInventories.Where(x => x.MaterialCode == shipping.MaterialCode).ToList();
                            if (InventoryList.Count() <= 0)
                            {
                                msg = "未查询到此物料";
                                tran.Rollback();
                                return false;
                            }
                            if (InventoryList.First().AvailableQty > shipping.Qty)
                            {
                                //回流调动堆垛机
                                TaskLiku task = new TaskLiku()
                                {
                                    taskId = shipping.OrderSn,
                                    taskSubType = "IN",
                                    startPositionId = stations.First().Code,
                                    endPositionId = palletBarAll.First().LocationCode,
                                    palletCode = palletBarAll.First().PalletBarcode
                                };
                                HttpHelper.WCSSendPostRequest("Api/ApiWCS/ReceiveTask", task);

                                //创建回流入库单
                                TReceivingOrderDetail receivingOrderDetail = new TReceivingOrderDetail();
                                DateTime now = DateTime.Now;
                                string year = now.Year.ToString();
                                string month = now.Month.ToString().PadLeft(2, '0');
                                string day = now.Day.ToString().PadLeft(2, '0');
                                string hour = now.Hour.ToString().PadLeft(2, '0');
                                string minute = now.Minute.ToString().PadLeft(2, '0');
                                string second = now.Second.ToString().PadLeft(2, '0');
                                receivingOrderDetail.OrderSn = "R" + $"{year}{month}{day}{hour}{minute}{second}";
                                receivingOrderDetail.BillType = 6;
                                receivingOrderDetail.WarehouseCode = shippingOrderAll.WarehouseCode;
                                var warehouseList = Context.TWarehouses.Where(x => x.Code == shippingOrderAll.WarehouseCode);
                                if (warehouseList.Count() <= 0)
                                {
                                    msg = "未查询到此库房";
                                    tran.Rollback();
                                    return false;
                                }
                                receivingOrderDetail.WarehouseName = warehouseList.First().Name;
                                receivingOrderDetail.MaterialId = shippingOrderAll.MaterialId;
                                receivingOrderDetail.MaterialCode = shippingOrderAll.MaterialCode;
                                receivingOrderDetail.MaterialName = shippingOrderAll.MaterialName;
                                receivingOrderDetail.MaterialTypeCode = shippingOrderAll.MaterialTypeCode;
                                receivingOrderDetail.AreaCode = shippingOrderAll.AreaCode;
                                receivingOrderDetail.AreaName = shippingOrderAll.AreaName;
                                receivingOrderDetail.PalletBarcode = PalletBarcode;
                                receivingOrderDetail.Qty = palletBarcodeInInventory.First().AvailableQty - shippingListAll.First().OutQty;
                                receivingOrderDetail.ReceivedQty = palletBarcodeInInventory.First().AvailableQty - shippingListAll.First().OutQty;
                                receivingOrderDetail.UnitId = shippingOrderAll.UnitId;
                                receivingOrderDetail.UnitName = shippingOrderAll.UnitName;
                                receivingOrderDetail.Erpcode = shippingOrderAll.Erpcode;
                                receivingOrderDetail.BatchNo = shippingOrderAll.BatchNo;
                                receivingOrderDetail.SmallBatchNo = shippingOrderAll.SmallBatchNo;
                                receivingOrderDetail.OwnerId = shippingOrderAll.OwnerId;
                                receivingOrderDetail.OwnerName = shippingOrderAll.OwnerName;
                                receivingOrderDetail.Status = 3;
                                receivingOrderDetail.LocationId = palletBarcodeInInventory.First().LocationId;
                                receivingOrderDetail.LocationName = palletBarcodeInInventory.First().LocationName;
                                receivingOrderDetail.LocationCode = palletBarcodeInInventory.First().LocationCode;
                                receivingOrderDetail.CreateDate = DateTime.Now;
                                receivingOrderDetail.MaterialName = shippingOrderAll.MaterialName;
                                receivingOrderDetail.Status = 2;
                                Context.TReceivingOrderDetails.Add(receivingOrderDetail);

                                decimal? returnQty = palletBarcodeInInventory.First().AvailableQty - shippingListAll.First().OutQty;
                                msg = "物料:" + shippingListAll.First().MaterialName + "回流" + returnQty;
                            }
                            else if (InventoryList.First().AvailableQty < shipping.Qty)
                            {
                                msg = "库存数量不满足出库数量";
                                tran.Rollback();
                                return false;
                            }
                            else
                            {
                                continue;
                            }

                        }
                    }
                    tran.Commit();
                    return true;
                }
                catch
                {
                    msg = "发生错误";
                    tran.Rollback();
                    return false;
                }

        }

        /// <summary>
        /// 获取托盘满载率
        /// </summary>
        /// <param name="PalletBarcode"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public decimal? GetPallLoadFactor(string PalletBarcode, out string msg)
        {
            msg = "";
            //获取托盘信息
            var palletList = Context.TPallets.Where(x => x.PalletBarcode == PalletBarcode).ToList();
            if(palletList.Count <= 0)
            {
                msg = "暂无此托盘";
                return 0;
            }
            //托盘总负荷
            decimal? palletWeight = palletList.First().MaximumWeightOfTray;       
            //获取出库单信息
            var shippingList = Context.TShippingLockCells.Where(x => x.PalletBarcode == PalletBarcode).ToList();
            if(shippingList.Count() <= 0)
            {
                msg = "该托盘未绑定出库单";
                return 0;
            }
            //物料重量
            decimal? materialGrossWeight = 0;
            //物料数量
            decimal? materialQty = 0;
            //物料总重量
            decimal? materialWeightSum = 0;
            decimal? num = 0;
            decimal? count = 0;
            foreach ( var shipping in shippingList )
            {
                var shippingOrderList = Context.TShippingOrderDetails.Where(x => x.OrderSn == shipping.OrdeSn).ToList();
                if(shippingOrderList.Count() <= 0)
                {
                    msg = "暂无出库单信息";
                    return 0;
                }
                
                foreach (var shippingOrder in shippingOrderList)
                {
                    if(shippingOrder.Status != 4 && shipping.OrdeSn == shippingOrder.OrderSn)
                    {
                        //获取物料
                        var materialList = Context.TMaterial.Where(x => x.Code == shippingOrder.MaterialCode).ToList();
                        if(materialList.Count() <= 0)
                        {
                            msg = "暂无此物料:" + shippingOrder.MaterialCode;
                            return 0;
                        }
                        //物料重量
                        materialGrossWeight = materialList.First().GrossWeight;
                        //物料数量
                        materialQty = shippingOrder.Qty;
                        //物料总重量
                        materialWeightSum = materialGrossWeight * materialQty;
                        num += materialWeightSum;
                      
                    }
                }
            }
            count = num / palletWeight;

            return count * 100;
        }

        /// <summary>
        /// 根据托盘条码带出相关信息
        /// </summary>
        /// <param name="PalletBarcode"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public InformationByBarcodeDto GetInformationByBarcode(string PalletBarcode, out string msg)
        {
            using (var tran = Context.Database.BeginTransaction())
            {
                try
                {
                    msg = "";
                    var palletBarAll = Context.TPallets.Where(x => x.PalletBarcode == PalletBarcode).ToList();
                    if (palletBarAll.Count() <= 0)
                    {
                        msg = "未查询到此托盘";
                        tran.Rollback();
                        return null;
                    }
                    //根据托盘查询出库单
                    var palletBar = palletBarAll.First();
                    var shippingListAll = Context.TShippingLockCells
                        .OrderByDescending(x => x.CreateDate)
                        .Where(x => x.PalletBarcode == PalletBarcode && x.CellCode == palletBar.LocationCode)
                        .ToList();
                    if(shippingListAll.Count() <= 0)
                    {
                        msg = "未查询到出库单相关数据";
                        return null ;
                    }
                    var shippingFirstOrderSn = shippingListAll.First().OrdeSn;
                    var shippingList = Context.TShippingLockCells.Where(x => x.OrdeSn == shippingFirstOrderSn).ToList();
                    if (shippingListAll.Count() <= 0)
                    {
                        msg = "未查询到出库单相关数据";
                        tran.Rollback();
                        return null;
                    }
                    foreach( var shipping in shippingListAll )
                    {
                        var shippingOrderAll = Context.TShippingOrderDetails
                            .OrderByDescending(x => x.CreateDate)
                            .Where(x => x.OrderSn == shipping.OrdeSn && x.Status != 4);
                        if (shippingOrderAll.Count() == 0)
                        {
                            msg = "此托盘暂无创建出库单";
                            tran.Rollback();
                            return null;
                        }
                        if (shippingOrderAll.First().Status == 4)
                        {
                            msg = "该出库单" + shippingOrderAll.First().OrderSn + "已完成,暂时无法带出数据";
                            tran.Rollback();
                            return null;
                        }

                        //查询库存表中此托盘有多少物料
                        var palletBarcodeInInventory = Context.TInventories.Where(x => x.PalletBarcode == PalletBarcode).ToList();
                        if (palletBarcodeInInventory.Count == 0)
                        {
                            msg = "此托盘中不存在物料";
                            tran.Rollback();
                            return null;
                        }
                        InformationByBarcodeDto informationByBarcodeDto = new InformationByBarcodeDto();
                        List<InformationByBarcodeChild> child = new List<InformationByBarcodeChild>();
                        foreach (var item in shippingList)
                        {
                            InformationByBarcodeChild informationByBarcodeChild = new InformationByBarcodeChild();
                            informationByBarcodeChild.MaterialCode = item.MaterialCode;
                            informationByBarcodeChild.MaterialName = item.MaterialName;
                            informationByBarcodeChild.InventoryQty = palletBarcodeInInventory.First().AvailableQty;
                            informationByBarcodeChild.OutQty = item.OutQty;
                            child.Add(informationByBarcodeChild);
                        }
                        informationByBarcodeDto.child = child;
                        informationByBarcodeDto.Barcode = PalletBarcode;
                        informationByBarcodeDto.LoadFactor = palletBarAll.First().LoadFactor;
                        informationByBarcodeDto.ShippingOrderSn = shippingOrderAll.First().OrderSn;
                        if (informationByBarcodeDto != null)
                        {
                            return informationByBarcodeDto;
                        }

                    }
                    msg = "未查询到数据";
                    tran.Commit();
                    return null;
                }
                catch
                {
                    msg = "发生错误！";
                    tran.Rollback();
                    return null;
                }
                
            }

        }
    }
}
